from fastapi import APIRouter, Response, File, UploadFile, Form
from fastapi.responses import JSONResponse
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
from requests.exceptions import RequestException
from colorthief import ColorThief
from PIL import Image
import io
from typing import Optional
import base64
from app.api.common.qrcode import QRCodeAPI
from app.api.common.zaobao import ZaobaoAPI
from app.api.common.star import StarAPI

router = APIRouter(prefix="/common")


@router.get("/bmi")
def calculate_bmi(weight: float, height: float, wunit: str = "斤", hunit: str = "厘米"):
    if wunit == "斤":
        weight = weight / 2
    if hunit == "厘米":
        height = height / 100
    bmi = weight / (height ** 2)
    return {"bmi": bmi}

@router.get('/favicon')
async def get_website_favicon(url: str):
    """
    获取指定网站的favicon图标并直接返回图片
    
    参数:
    - url: 目标网站的URL
    
    返回:
    - 图标图片的二进制数据或错误信息的JSON
    """
    # 验证URL格式
    if not url or len(url.strip()) == 0:
        return JSONResponse(
            content={"error": "URL不能为空", "code": 400},
            status_code=200,
            media_type="application/json; charset=utf-8"
        )

    # 确保URL格式正确
    if not url.startswith(('http://', 'https://')):
        url = 'https://' + url

    # 尝试解析URL以验证其有效性
    try:
        parsed = urlparse(url)
        if not parsed.netloc:
            return JSONResponse(
                content={"error": "无效的URL格式", "code": 400},
                status_code=200,
                media_type="application/json; charset=utf-8"
            )
    except Exception:
        return JSONResponse(
            content={"error": "无效的URL格式", "code": 400},
            status_code=200,
            media_type="application/json; charset=utf-8"
        )

    # 获取网站内容
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    }

    try:
        web_response = requests.get(url, headers=headers, timeout=5)
        web_response.raise_for_status()
    except RequestException as e:
        # 处理请求异常，如连接超时、DNS解析失败等
        error_msg = ""
        error_code = 400

        if "Name or service not known" in str(e) or "getaddrinfo failed" in str(e):
            error_msg = "无法解析域名，请检查URL是否正确"
        elif "Connection refused" in str(e):
            error_msg = "连接被拒绝，网站可能不可用"
        elif "timed out" in str(e):
            error_msg = "连接超时，请稍后再试"
            error_code = 408
        elif hasattr(e, 'response') and e.response is not None:
            error_code = e.response.status_code
            error_msg = f"网站返回错误: HTTP {error_code}"
        else:
            error_msg = f"无法访问网站: {str(e)}"

        return JSONResponse(
            content={"error": error_msg, "code": error_code},
            status_code=200,
            media_type="application/json; charset=utf-8"
        )

    # 解析网站内容
    try:
        soup = BeautifulSoup(web_response.text, 'html.parser')
    except Exception as e:
        return {"error": f"解析网页内容失败: {str(e)}", "code": 400}

    # 查找favicon的可能位置
    favicon_url = None

    # 方法1: 查找link标签中的favicon
    icons = soup.find_all('link', rel=lambda r: r and ('icon' in r.lower() or 'shortcut icon' in r.lower()))
    if icons:
        href = icons[0].get('href')
        if href:
            favicon_url = urljoin(url, href)

    # 方法2: 如果没找到，尝试默认位置
    if not favicon_url:
        parsed_url = urlparse(url)
        root_url = f"{parsed_url.scheme}://{parsed_url.netloc}"
        favicon_url = urljoin(root_url, '/favicon.ico')

    # 获取图标图片
    if favicon_url:
        try:
            img_response = requests.get(favicon_url, timeout=3)
            if img_response.status_code == 200 and len(img_response.content) > 0:
                # 设置正确的内容类型
                content_type = img_response.headers.get('Content-Type', 'image/x-icon')

                # 直接返回Response对象，而不是返回内容
                return Response(content=img_response.content, media_type=content_type)
        except RequestException:
            # 如果获取图标失败，继续尝试下一个方法或返回默认图标
            pass

    # 如果没有找到图标，返回404错误
    return JSONResponse(
        content={"error": "未找到网站图标", "code": 404},
        status_code=200,
        media_type="application/json; charset=utf-8"
    )


@router.post('/extract-color')
async def extract_dominant_color(
        image_url: Optional[str] = Form(None),
        image_file: Optional[UploadFile] = File(None),
        palette_size: int = Form(9)
):
    """
    使用ColorThief提取图片的主色调和调色板
    
    参数:
    - image_url: 图片的URL地址（可选）
    - image_file: 上传的图片文件（可选）
    - palette_size: 调色板大小，默认为9
    
    返回:
    - 包含主色调和调色板信息的JSON
    """
    if not image_url and not image_file:
        return JSONResponse(
            content={"error": "请提供图片URL或上传图片文件", "code": 400},
            status_code=200,
            media_type="application/json; charset=utf-8"
        )

    try:
        # 获取图片数据
        if image_url:
            # 从URL获取图片
            try:
                response = requests.get(image_url, timeout=10)
                response.raise_for_status()
                image_data = response.content
            except Exception as e:
                return JSONResponse(
                    content={"error": f"无法从URL获取图片: {str(e)}", "code": 400},
                    status_code=200,
                    media_type="application/json; charset=utf-8"
                )
        else:
            # 从上传的文件获取图片
            image_data = await image_file.read()

        # 创建BytesIO对象
        image_bytes = io.BytesIO(image_data)

        # 使用ColorThief提取颜色
        try:
            color_thief = ColorThief(image_bytes)

            # 获取主色调
            dominant_color = color_thief.get_color(quality=10)

            # 获取调色板
            palette_size = min(max(2, palette_size), 10)  # 限制在2-10之间
            palette = color_thief.get_palette(color_count=palette_size, quality=10)

        except Exception as e:
            # 如果ColorThief处理失败，尝试先用PIL打开并转换图片格式
            try:
                image = Image.open(image_bytes)
                # 转换为RGB模式（处理PNG等带透明通道的图片）
                if image.mode != 'RGB':
                    image = image.convert('RGB')

                # 保存为JPEG格式的BytesIO对象
                converted_bytes = io.BytesIO()
                image.save(converted_bytes, format='JPEG')
                converted_bytes.seek(0)

                # 重新尝试ColorThief
                color_thief = ColorThief(converted_bytes)
                dominant_color = color_thief.get_color(quality=10)
                palette = color_thief.get_palette(color_count=palette_size, quality=10)

            except Exception as e2:
                return JSONResponse(
                    content={"error": f"无法处理图片: {str(e2)}", "code": 400},
                    status_code=200,
                    media_type="application/json; charset=utf-8"
                )

        # 格式化主色调
        r, g, b = dominant_color
        dominant_hex = f"#{r:02x}{g:02x}{b:02x}"

        # 格式化调色板
        palette_colors = []
        for color in palette:
            r, g, b = color
            hex_color = f"#{r:02x}{g:02x}{b:02x}"
            palette_colors.append({
                "rgb": [r, g, b],
                "hex": hex_color
            })

        # 生成预览图
        preview_width = 200
        preview_height = 50
        preview = Image.new('RGB', (preview_width, preview_height))

        # 绘制主色调部分
        for x in range(int(preview_width * 0.3)):
            for y in range(preview_height):
                preview.putpixel((x, y), dominant_color)

        # 绘制调色板部分
        palette_width = int(preview_width * 0.7)
        color_width = palette_width // len(palette_colors)
        for i, color in enumerate(palette_colors):
            for x in range(int(preview_width * 0.3) + i * color_width,
                           min(int(preview_width * 0.3) + (i + 1) * color_width, preview_width)):
                for y in range(preview_height):
                    preview.putpixel((x, y), tuple(color["rgb"]))

        # 将预览图转换为base64
        buffer = io.BytesIO()
        preview.save(buffer, format="PNG")
        preview_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')

        return {
            "dominant_color": {
                "rgb": list(dominant_color),
                "hex": dominant_hex
            },
            "palette": palette_colors,
            "preview": f"data:image/png;base64,{preview_base64}"
        }

    except Exception as e:
        return JSONResponse(
            content={"error": f"提取颜色失败: {str(e)}", "code": 500},
            status_code=200,
            media_type="application/json; charset=utf-8"
        )

@router.get('/qrcode')
async def get_qrcode(
    text: str, 
    box_size: int = 10, 
    border: int = 4, 
    fill_color: str = "black", 
    back_color: str = "white", 
    format: str = "image"
):
    """
    生成二维码并返回
    
    参数:
    - text: 要编码的文本
    - box_size: 二维码中每个格子的像素大小
    - border: 二维码边框宽度(格子数)
    - fill_color: 二维码颜色
    - back_color: 背景颜色
    - format: 返回格式，'png'返回图片，'base64'返回base64编码
    
    返回:
    - 二维码图片或base64编码的JSON
    """
    qrcode_api = QRCodeAPI()
    return qrcode_api.handle(
        text=text, 
        box_size=box_size, 
        border=border, 
        fill_color=fill_color, 
        back_color=back_color, 
        format=format
    )


@router.get('/zaobao')
async def get_zaobao(type: str = "json"):
    """
    获取早报信息并返回
    
    参数:
    - type: 返回格式，'json'返回JSON格式, 'html'返回HTML格式
   
    
    返回:
    - 早报信息的JSON或图片信息
    """
    return ZaobaoAPI().handle(type)

@router.get('/star')
async def get_star(star: str):
    """
    获取今日运势
    
    参数:
    - star: 星座名称
    
    返回:
    - 星座运势的JSON
    """
    star_api = StarAPI()
    return star_api.handle(star)
    